# -*- coding: utf-8 -*-
# @Author: fanmingxiang@touty.io
# @Date: 2023/3/31 22:10
import copy
import json
import os
import threading
from time import sleep

from django.conf import settings
from django.shortcuts import render
from django.http import JsonResponse, HttpResponse
# Create your views here.
from apitests.models import ApiDefine, ApiCase, ApiAutoTest, CaseTemporary
from apitests.run_test_cases import run_test_cases
from common.pagination import Pagination
from common.send_email import send_report
from common.threading_result import ThreadTimer
from projects.models import Projects, Modules
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger

from test_reports.models import TestReports, ReportDescribe

CURRENT_PATH = settings.BASE_DIR + os.sep + 'apitests'


def api_case_auto(request):
    try:
        page = request.GET.get('page', 1)
    except PageNotAnInteger:
        page = 1
    nums = request.GET.get('nums', None)
    search_text = request.GET.get('Search', '')
    search_dict = {}

    projects_list = Projects.objects.all().order_by('-create_time')
    is_project = int(request.COOKIES['Project'])
    if is_project:
        project_id = projects_list.get(id=is_project)
        api_auto_set = project_id.apiautotest_set.all()
        api_auto_id_list = [api_auto.id for api_auto in api_auto_set]
        search_dict['id__in'] = api_auto_id_list
    if search_text:
        search_dict['name__contains'] = search_text
    api_case_list = ApiAutoTest.objects.filter(**search_dict).order_by('-create_time')
    content = Pagination(api_case_list, search_text, page, nums).per_page()
    content['projects_list'] = projects_list
    content['is_project'] = is_project

    return render(request, 'api_case_auto_list.html', content)


def api_auto_del(request):
    api_auto_id = request.POST['api_auto_id']
    ApiAutoTest.objects.filter(id=api_auto_id).delete()
    return JsonResponse({"status": True})


def api_auto_add(request):
    user = request.user
    api_case_name = request.POST['api_case_name']
    api_case_priority = request.POST['api_case_priority']
    api_case_describe = request.POST['api_case_describe']
    api_project = int(request.POST['api_project'])
    if api_case_name:
        api_auto = ApiAutoTest(name=api_case_name, priority=api_case_priority, describe=api_case_describe, creator=user,
                               project_id=api_project, cases='[]')
        api_auto.save()
        return JsonResponse({"status": True})
    return JsonResponse({"status": False})


def api_auto_copy(request):
    api_auto_id = request.POST['api_auto_id']
    api_auto_test = ApiAutoTest.objects.get(id=api_auto_id)
    auto_copy = copy.deepcopy(api_auto_test)
    auto_copy.pk = None
    auto_copy.name = api_auto_test.name + "(复制)"
    auto_copy.save()
    return JsonResponse({"status": True})


def api_auto_edit(request):
    if request.method == "GET":
        api_auto_id = request.GET.get('api_auto_id')
        project_id = request.GET.get('project_id')
        api_auto = ApiAutoTest.objects.get(id=api_auto_id)
        case_list = []
        projects_list = Projects.objects.all().order_by('-create_time')
        is_project = int(request.COOKIES['Project'])
        report_list = []
        test_reports = TestReports.objects.filter(api_auto_id=api_auto).order_by('-create_time')
        for test_report in test_reports:
            report_dict = {}
            report_dict['report_id'] = test_report.id
            report_dict['title'] = test_report.title
            report_dict['test_all_count'] = test_report.test_all_count
            report_dict['success_count'] = test_report.success_count
            try:
                report_dict['pass_rate'] = round((test_report.success_count / test_report.test_all_count) * 100, 2)
            except ZeroDivisionError:
                report_dict['pass_rate'] = 0
            report_dict['status'] = test_report.status
            report_dict['create_time'] = test_report.create_time
            report_dict['tester'] = test_report.tester
            report_list.append(report_dict)
        if api_auto.cases:
            for case in json.loads(api_auto.cases):
                case_dict = {}
                try:
                    case = ApiCase.objects.get(id=case)
                    case_dict['id'] = case.id
                    case_dict['method'] = case.get_method_display()
                    case_dict['case_name'] = case.name
                    case_dict['api_name'] = case.api_define
                    case_dict['interface'] = case.interface
                    case_list.append(case_dict)
                except Exception:
                    continue
        return render(request, 'api_auto_edit.html',
                      {"api_auto": api_auto, "project_id": project_id, "case_list": case_list,
                       "projects_list": projects_list, "is_project": is_project, "report_list": report_list})
    api_auto_id = request.POST['api_auto_id']
    api_case_name = request.POST['api_case_name']
    api_case_priority = request.POST['api_case_priority']
    api_case_describe = request.POST['api_case_describe']
    api_auto = ApiAutoTest.objects.get(id=api_auto_id)
    api_auto.name = api_case_name
    api_auto.priority = api_case_priority
    api_auto.describe = api_case_describe
    api_auto.save()
    return JsonResponse({"status": True})


def api_step_save(request):
    step_id = request.POST['step_id']
    api_id = request.POST['api_id']
    user = request.user
    case = ApiAutoTest.objects.get(id=api_id)
    case.cases = step_id
    case.u_creator = str(user)
    case.save()
    return JsonResponse({"status": True})


def api_case_run(request):
    api_auto_id = request.POST['api_auto_id']
    user = request.user
    return JsonResponse(AutoThread(api_auto_id, user).run_cases())


class AutoThread:
    def __init__(self, api_auto_id, user):
        self.api_auto_id = api_auto_id
        self.user = user

    def run_cases(self):
        api_auto = ApiAutoTest.objects.get(id=self.api_auto_id)
        test_data = {}
        for case_id in json.loads(api_auto.cases):
            try:
                api_case = ApiCase.objects.get(id=case_id)
                # case_temporary = CaseTemporary(name=api_case.name, interface=api_case.interface,
                #                                method=api_case.method, params=api_case.params,
                #                                headers=api_case.headers,
                #                                body_type=api_case.body_type, body=api_case.body,
                #                                is_assert=api_case.is_assert,
                #                                assert_type=api_case.assert_type, assert_body=api_case.assert_body,
                #                                )
                # case_temporary.save()
                if api_case.body == '':
                    api_case.body = "{}"
                test_data[api_case.name] = {
                    "method": api_case.get_method_display(),
                    "url": api_case.interface,
                    "headers": json.loads(api_case.headers),
                    "params": json.loads(api_case.params),
                    "body_type": api_case.body_type,
                    "body": json.loads(api_case.body),
                    "is_assert": api_case.is_assert,
                    "assert_type": api_case.assert_type,
                    "assert_body": api_case.assert_body
                }
            except:
                continue
        if test_data:
            case_data = json.dumps(test_data, ensure_ascii=False, indent=1)
            filepath = CURRENT_PATH + os.sep + 'templates\json\case_data.json'
            with open(filepath, 'w', encoding='utf-8') as f:
                f.write(case_data)
                f.close()
            test_report = TestReports(title=api_auto.name, status=0, api_auto=api_auto, tester=self.user)
            test_report.save()
            run_test_cases(filepath, test_report.id)
            # run_suite(test_report.id, test_report.title)
            # dance_process = Process(target=run_suite, args=(test_report.id, test_report.title))
            # dance_process.start()
            # run_cmd = "python " + CURRENT_PATH + r"\run_cases.py"
            # os.system(run_cmd)
            # t1 = threading.Thread(target=run_suite, args=(test_report.id, test_report.title))
            # t1.start()
            t = ThreadTimer(1, AutoThread.wait_report_status, args=(test_report.id,))
            t.start()
            t.join()
            while t.get_result()["status"]:
                t1 = threading.Thread(target=send_report, args=(test_report.id,self.user.email))
                t1.start()
                break
            return t.get_result()
        else:
            return {"status": False, "error_msg": "检测到无用例，无需执行"}

    @classmethod
    def wait_report_status(cls, report_id):
        test_report = TestReports.objects.get(id=report_id)
        if test_report.status == 1:
            return {"status": True, "report_id": report_id}
        sleep(0.5)
        AutoThread.wait_report_status(report_id)


def case_show_report(request):
    url = request.GET['url']
    return render(request, 'report/' + url)


def report_show(request):
    report_id = request.GET['report_id']
    test_reports = TestReports.objects.get(id=report_id)
    report_describe = ReportDescribe.objects.filter(test_report=test_reports)
    content = {
        "title": test_reports.title,
        "startTime": f"{test_reports.startTime}",
        "duration": test_reports.stopTime - test_reports.startTime,
        "test_all_count": test_reports.test_all_count,
        "success_count": test_reports.success_count,
        "failure_count": test_reports.failure_count,
        "error_count": test_reports.error_count,
        "pass_rate": f"{test_reports.success_count / test_reports.test_all_count:.2%}",
        "pass_rate_value": f"{test_reports.success_count / test_reports.test_all_count:.2%}"[:-1],
        "report_describe": report_describe

    }
    return render(request, "report.html", content)


def get_case_tree(request):
    project_id = request.GET.get('project_id')
    modules = Modules.objects.filter(project=project_id)
    api_defines_list = []
    for module in modules:
        api_defines = ApiDefine.objects.filter(module_id=module.id).order_by('-create_time')

        for api_define in api_defines:
            name = api_define.get_method_display() + '    ' + api_define.name + '    ' + api_define.interface
            api_define_data = {
                "name": name,
                "isParent": True,
            }
            api_cases = ApiCase.objects.filter(api_define_id=api_define.id)
            api_cases_list = []
            for api_case in api_cases:
                api_case_data = {
                    "api_define_name": api_define.name,
                    "name": api_case.name,
                    "isParent": False,
                    "id": api_case.id,
                    "method": api_case.get_method_display(),
                    "url": api_case.interface
                }
                api_cases_list.append(api_case_data)
            api_define_data['children'] = api_cases_list
            api_defines_list.append(api_define_data)
    return JsonResponse({"status": 10200, "data": api_defines_list})

#
# EXTEND_DIR = BASE_PATH
# def api_run_case(request):
#     api_define_id = request.GET.get('api_define_id')
#     api_define = ApiDefine.objects.get(id=api_define_id)
#     test_data = {}
#     test_data[api_define.name] = {
#         "url": api_define.interface,
#         "params": api_define.params,
#         "headers": api_define.headers,
#         "body_type": api_define.get_body_type_display(),
#         "assert_type": api_define.get_assert_type_display(),
#         "assert_body": api_define.assert_body,
#         "api_body": api_define.body
#
#     }
#     json_data = json.dumps(test_data)
#     with open(EXTEND_DIR + 'case_data.json', 'w', encoding='utf-8') as f:
#         f.write(json_data)
#
#     return HttpResponse('ok')
